home *** CD-ROM | disk | FTP | other *** search
/ Programming a Multiplayer FPS in DirectX / Programming a Multiplayer FPS in DirectX (Companion CD).iso / DirectX / dxsdk_oct2004.exe / dxsdk.exe / Samples / C++ / Direct3D / Text3D / text3d.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-09-27  |  31.7 KB  |  707 lines

  1. //--------------------------------------------------------------------------------------
  2. // File: Text3D.cpp
  3. //
  4. // Desc: Example code showing how to do text in a Direct3D scene.
  5. //
  6. // Copyright (c) Microsoft Corporation. All rights reserved.
  7. //--------------------------------------------------------------------------------------
  8. #include "dxstdafx.h"
  9. #include <commdlg.h>
  10. #include "resource.h"
  11.  
  12.  
  13. //--------------------------------------------------------------------------------------
  14. // Global variables
  15. //--------------------------------------------------------------------------------------
  16. ID3DXSprite*        g_pTextSprite = NULL;   // Sprite for batching draw text calls
  17. CFirstPersonCamera  g_Camera;               // A model viewing camera
  18. bool                g_bShowHelp = true;     // If true, it renders the UI control text
  19. CDXUTDialog         g_HUD;                  // dialog for standard controls
  20. CDXUTDialog         g_SampleUI;             // dialog for sample specific controls
  21.  
  22. ID3DXFont*          g_pFont = NULL;
  23. ID3DXFont*          g_pFont2 = NULL;
  24. ID3DXFont*          g_pStatsFont = NULL;
  25. ID3DXMesh*          g_pMesh3DText = NULL;
  26. WCHAR*              g_strTextBuffer = NULL;
  27.  
  28. TCHAR               g_strFont[LF_FACESIZE];
  29. int                 g_nFontSize;
  30.  
  31. D3DXMATRIXA16       g_matObj1;
  32. D3DXMATRIXA16       g_matObj2;
  33.  
  34.  
  35. //--------------------------------------------------------------------------------------
  36. // UI control IDs
  37. //--------------------------------------------------------------------------------------
  38. #define IDC_TOGGLEFULLSCREEN    1
  39. #define IDC_TOGGLEREF           3
  40. #define IDC_CHANGEDEVICE        4
  41. #define IDC_CHANGEFONT          5
  42.  
  43.  
  44.  
  45. //--------------------------------------------------------------------------------------
  46. // Forward declarations 
  47. //--------------------------------------------------------------------------------------
  48. bool    CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat, bool bWindowed );
  49. void    CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps );
  50. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  51. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc );
  52. void    CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  53. void    CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime );
  54. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing );
  55. void    CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown  );
  56. void    CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl );
  57. void    CALLBACK OnLostDevice();
  58. void    CALLBACK OnDestroyDevice();
  59.  
  60. void    InitApp();
  61. HRESULT CreateD3DXTextMesh( IDirect3DDevice9* pd3dDevice, LPD3DXMESH* ppMesh, TCHAR* pstrFont, DWORD dwSize, BOOL bBold, BOOL bItalic );
  62. HRESULT CreateD3DXFont( LPD3DXFONT* ppd3dxFont, TCHAR* pstrFont, DWORD dwSize );
  63.  
  64.  
  65. //--------------------------------------------------------------------------------------
  66. // Entry point to the program. Initializes everything and goes into a message processing 
  67. // loop. Idle time is used to render the scene.
  68. //--------------------------------------------------------------------------------------
  69. INT WINAPI WinMain( HINSTANCE, HINSTANCE, LPSTR, int )
  70. {
  71.     // Set the callback functions. These functions allow the sample framework to notify
  72.     // the application about device changes, user input, and windows messages.  The 
  73.     // callbacks are optional so you need only set callbacks for events you're interested 
  74.     // in. However, if you don't handle the device reset/lost callbacks then the sample 
  75.     // framework won't be able to reset your device since the application must first 
  76.     // release all device resources before resetting.  Likewise, if you don't handle the 
  77.     // device created/destroyed callbacks then the sample framework won't be able to 
  78.     // recreate your device resources.
  79.     DXUTSetCallbackDeviceCreated( OnCreateDevice );
  80.     DXUTSetCallbackDeviceReset( OnResetDevice );
  81.     DXUTSetCallbackDeviceLost( OnLostDevice );
  82.     DXUTSetCallbackDeviceDestroyed( OnDestroyDevice );
  83.     DXUTSetCallbackMsgProc( MsgProc );
  84.     DXUTSetCallbackKeyboard( KeyboardProc );
  85.     DXUTSetCallbackFrameRender( OnFrameRender );
  86.     DXUTSetCallbackFrameMove( OnFrameMove );
  87.  
  88.     // Show the cursor and clip it when in full screen
  89.     DXUTSetCursorSettings( true, true );
  90.     InitApp();
  91.  
  92.     // Initialize the sample framework and create the desired Win32 window and Direct3D 
  93.     // device for the application. Calling each of these functions is optional, but they
  94.     // allow you to set several options which control the behavior of the framework.
  95.     DXUTInit( true, true, true ); // Parse the command line, handle the default hotkeys, and show msgboxes
  96.     DXUTCreateWindow( L"Text3D" );
  97.     DXUTCreateDevice( D3DADAPTER_DEFAULT, true, 640, 480, IsDeviceAcceptable, ModifyDeviceSettings );
  98.  
  99.     // Pass control to the sample framework for handling the message pump and 
  100.     // dispatching render calls. The sample framework will call your FrameMove 
  101.     // and FrameRender callback when there is idle time between handling window messages.
  102.     DXUTMainLoop();
  103.  
  104.     // Perform any application-level cleanup here. Direct3D device resources are released within the
  105.     // appropriate callback functions and therefore don't require any cleanup code here.
  106.     SAFE_DELETE_ARRAY( g_strTextBuffer );
  107.  
  108.     return DXUTGetExitCode();
  109. }
  110.  
  111.  
  112. //--------------------------------------------------------------------------------------
  113. // Initialize the app 
  114. //--------------------------------------------------------------------------------------
  115. void InitApp()
  116. {
  117.     wcscpy( g_strFont, L"Arial" );
  118.  
  119.     HRSRC rsrc;
  120.     HGLOBAL hgData;
  121.     LPVOID pvData;
  122.     DWORD cbData;
  123.  
  124.     rsrc = FindResource( NULL, MAKEINTRESOURCE(IDR_TXT), L"TEXT" );
  125.     if( rsrc != NULL )
  126.     {
  127.         cbData = SizeofResource( NULL, rsrc );
  128.         if( cbData > 0 )
  129.         {
  130.             hgData = LoadResource( NULL, rsrc );
  131.             if( hgData != NULL )
  132.             {
  133.                 pvData = LockResource( hgData );
  134.                 if( pvData != NULL )
  135.                 {
  136.                     int nSize = cbData/sizeof(WCHAR) + 1;
  137.                     g_strTextBuffer = new WCHAR[nSize];
  138.                     memcpy( g_strTextBuffer, (WCHAR*)pvData, cbData );
  139.                     g_strTextBuffer[nSize-1] = 0;
  140.                 }
  141.             }
  142.         }
  143.     }
  144.  
  145.     // Initialize dialogs
  146.     g_HUD.SetCallback( OnGUIEvent ); int iY = 10; 
  147.     g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 35, iY, 125, 22 );
  148.     g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 35, iY += 24, 125, 22 );
  149.     g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 35, iY += 24, 125, 22 );
  150.  
  151.     g_SampleUI.SetCallback( OnGUIEvent ); iY = 10; 
  152.     g_SampleUI.AddButton( IDC_CHANGEFONT, L"Change Font", 35, iY += 24, 125, 22 );
  153. }
  154.  
  155.  
  156. //--------------------------------------------------------------------------------------
  157. // Called during device initialization, this code checks the device for some 
  158. // minimum set of capabilities, and rejects those that don't pass by returning false.
  159. //--------------------------------------------------------------------------------------
  160. bool CALLBACK IsDeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, 
  161.                                   D3DFORMAT BackBufferFormat, bool bWindowed )
  162. {
  163.     // Skip backbuffer formats that don't support alpha blending
  164.     IDirect3D9* pD3D = DXUTGetD3DObject(); 
  165.     if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
  166.                     AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING, 
  167.                     D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
  168.         return false;
  169.  
  170.     return true;
  171. }
  172.  
  173.  
  174. //--------------------------------------------------------------------------------------
  175. // This callback function is called immediately before a device is created to allow the 
  176. // application to modify the device settings. The supplied pDeviceSettings parameter 
  177. // contains the settings that the framework has selected for the new device, and the 
  178. // application can make any desired changes directly to this structure.  Note however that 
  179. // the sample framework will not correct invalid device settings so care must be taken 
  180. // to return valid device settings, otherwise IDirect3D9::CreateDevice() will fail.  
  181. //--------------------------------------------------------------------------------------
  182. void CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, const D3DCAPS9* pCaps )
  183. {
  184.     // If device doesn't support HW T&L or doesn't support 1.1 vertex shaders in HW 
  185.     // then switch to SWVP.
  186.     if( (pCaps->DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0 ||
  187.          pCaps->VertexShaderVersion < D3DVS_VERSION(1,1) )
  188.     {
  189.         pDeviceSettings->BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  190.     }
  191.     else
  192.     {
  193.         pDeviceSettings->BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
  194.     }
  195.  
  196.     // This application is designed to work on a pure device by not using 
  197.     // IDirect3D9::Get*() methods, so create a pure device if supported and using HWVP.
  198.     if ((pCaps->DevCaps & D3DDEVCAPS_PUREDEVICE) != 0 && 
  199.         (pDeviceSettings->BehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING) != 0 )
  200.         pDeviceSettings->BehaviorFlags |= D3DCREATE_PUREDEVICE;
  201.  
  202.     // Debugging vertex shaders requires either REF or software vertex processing 
  203.     // and debugging pixel shaders requires REF.  
  204. #ifdef DEBUG_VS
  205.     if( pDeviceSettings->DeviceType != D3DDEVTYPE_REF )
  206.     {
  207.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_HARDWARE_VERTEXPROCESSING;
  208.         pDeviceSettings->BehaviorFlags &= ~D3DCREATE_PUREDEVICE;                            
  209.         pDeviceSettings->BehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
  210.     }
  211. #endif
  212. #ifdef DEBUG_PS
  213.     pDeviceSettings->DeviceType = D3DDEVTYPE_REF;
  214. #endif
  215. }
  216.  
  217.  
  218. //--------------------------------------------------------------------------------------
  219. // This callback function will be called immediately after the Direct3D device has been 
  220. // created, which will happen during application initialization and windowed/full screen 
  221. // toggles. This is the best location to create D3DPOOL_MANAGED resources since these 
  222. // resources need to be reloaded whenever the device is destroyed. Resources created  
  223. // here should be released in the OnDestroyDevice callback. 
  224. //--------------------------------------------------------------------------------------
  225. HRESULT CALLBACK OnCreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  226. {
  227.     HRESULT hr;
  228.  
  229.     HDC hDC = GetDC( NULL );
  230.     int nLogPixelsY = GetDeviceCaps(hDC, LOGPIXELSY);
  231.     ReleaseDC( NULL, hDC );
  232.  
  233.     int nHeight = -g_nFontSize * nLogPixelsY / 72;
  234.     hr = D3DXCreateFont( pd3dDevice,            // D3D device
  235.                          nHeight,               // Height
  236.                          0,                     // Width
  237.                          FW_BOLD,               // Weight
  238.                          1,                     // MipLevels, 0 = autogen mipmaps
  239.                          FALSE,                 // Italic
  240.                          DEFAULT_CHARSET,       // CharSet
  241.                          OUT_DEFAULT_PRECIS,    // OutputPrecision
  242.                          DEFAULT_QUALITY,       // Quality
  243.                          DEFAULT_PITCH | FF_DONTCARE, // PitchAndFamily
  244.                          g_strFont,              // pFaceName
  245.                          &g_pFont);              // ppFont
  246.     if( FAILED( hr ) )
  247.         return hr;
  248.  
  249.     if( FAILED( hr = D3DXCreateFont( pd3dDevice, -12, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  250.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  251.                          L"System", &g_pFont2 ) ) )
  252.         return hr;
  253.  
  254.     if( FAILED( hr = D3DXCreateFont( pd3dDevice, 15, 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET, 
  255.                          OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  256.                          L"Arial", &g_pStatsFont ) ) )
  257.         return hr;
  258.  
  259.     if( FAILED( hr = D3DXCreateSprite( pd3dDevice, &g_pTextSprite ) ) )
  260.         return hr;
  261.  
  262.     return S_OK;
  263. }
  264.  
  265.  
  266. //--------------------------------------------------------------------------------------
  267. // This callback function will be called immediately after the Direct3D device has been 
  268. // reset, which will happen after a lost device scenario. This is the best location to 
  269. // create D3DPOOL_DEFAULT resources since these resources need to be reloaded whenever 
  270. // the device is lost. Resources created here should be released in the OnLostDevice 
  271. // callback. 
  272. //--------------------------------------------------------------------------------------
  273. HRESULT CALLBACK OnResetDevice( IDirect3DDevice9* pd3dDevice, 
  274.                                 const D3DSURFACE_DESC* pBackBufferSurfaceDesc )
  275. {
  276.     g_HUD.SetLocation( pBackBufferSurfaceDesc->Width-170, 0 );
  277.     g_HUD.SetSize( 170, 170 );
  278.     g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width-170, pBackBufferSurfaceDesc->Height-350 );
  279.     g_SampleUI.SetSize( 170, 300 );
  280.  
  281.     // Restore the fonts
  282.     g_pStatsFont->OnResetDevice();
  283.     g_pFont->OnResetDevice();
  284.     g_pFont2->OnResetDevice();
  285.     g_pTextSprite->OnResetDevice();
  286.  
  287.     // Restore the textures
  288.     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
  289.     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
  290.     pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE );
  291.     pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR );
  292.     pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR );
  293.  
  294.     pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
  295.     pd3dDevice->SetRenderState( D3DRS_DITHERENABLE, TRUE );
  296.     pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
  297.     pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
  298.     pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x80808080);
  299.     D3DLIGHT9 light;
  300.     D3DXVECTOR3 vecLightDirUnnormalized(10.0f, -10.0f, 10.0f);
  301.     ZeroMemory( &light, sizeof(D3DLIGHT9) );
  302.     light.Type        = D3DLIGHT_DIRECTIONAL;
  303.     light.Diffuse.r   = 1.0f;
  304.     light.Diffuse.g   = 1.0f;
  305.     light.Diffuse.b   = 1.0f;
  306.     D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecLightDirUnnormalized );
  307.     light.Position.x   = 10.0f;
  308.     light.Position.y   = -10.0f;
  309.     light.Position.z   = 10.0f;
  310.     light.Range        = 1000.0f;
  311.     pd3dDevice->SetLight(0, &light );
  312.     pd3dDevice->LightEnable(0, TRUE);
  313.  
  314.     // Set the transform matrices
  315.     D3DXMATRIXA16  matWorld;
  316.     D3DXMatrixIdentity( &matWorld );
  317.     pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
  318.  
  319.     // Setup the camera with view & projection matrix
  320.     D3DXVECTOR3 vecEye(0.0f,-5.0f, -10.0f);
  321.     D3DXVECTOR3 vecAt (0.2f, 0.0f, 0.0f);
  322.     g_Camera.SetViewParams( &vecEye, &vecAt );
  323.     float fAspectRatio = pBackBufferSurfaceDesc->Width / (FLOAT)pBackBufferSurfaceDesc->Height;
  324.     g_Camera.SetProjParams( D3DX_PI/4, fAspectRatio, 1.0f, 1000.0f );
  325.  
  326.     SAFE_RELEASE( g_pMesh3DText );
  327.     if( FAILED( CreateD3DXTextMesh( pd3dDevice, &g_pMesh3DText, g_strFont, g_nFontSize, FALSE, FALSE ) ) )
  328.         return E_FAIL;
  329.  
  330.     return S_OK;
  331. }
  332.  
  333.  
  334. //-----------------------------------------------------------------------------
  335. // Name: CreateD3DXTextMesh()
  336. // Desc: 
  337. //-----------------------------------------------------------------------------
  338. HRESULT CreateD3DXTextMesh( IDirect3DDevice9* pd3dDevice, 
  339.                             LPD3DXMESH* ppMesh, 
  340.                             TCHAR* pstrFont, DWORD dwSize,
  341.                             BOOL bBold, BOOL bItalic )
  342. {
  343.     HRESULT hr;
  344.     LPD3DXMESH pMeshNew = NULL;
  345.     HDC hdc = CreateCompatibleDC( NULL );
  346.     INT nHeight = -MulDiv( dwSize, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
  347.     HFONT hFont;
  348.     HFONT hFontOld;
  349.  
  350.     hFont = CreateFont(nHeight, 0, 0, 0, bBold ? FW_BOLD : FW_NORMAL, bItalic, FALSE, FALSE, DEFAULT_CHARSET, 
  351.         OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, pstrFont);
  352.     
  353.     hFontOld = (HFONT)SelectObject(hdc, hFont); 
  354.  
  355.     hr = D3DXCreateText( pd3dDevice, hdc, L"This is calling D3DXCreateText", 
  356.                          0.001f, 0.4f, &pMeshNew, NULL, NULL);
  357.  
  358.     SelectObject(hdc, hFontOld);
  359.     DeleteObject( hFont );
  360.     DeleteDC( hdc );
  361.  
  362.     if( SUCCEEDED( hr ) )
  363.         *ppMesh = pMeshNew;
  364.  
  365.     return hr;
  366. }
  367.  
  368.  
  369.  
  370.  
  371. //--------------------------------------------------------------------------------------
  372. // This callback function will be called once at the beginning of every frame. This is the
  373. // best location for your application to handle updates to the scene, but is not 
  374. // intended to contain actual rendering calls, which should instead be placed in the 
  375. // OnFrameRender callback.  
  376. //--------------------------------------------------------------------------------------
  377. void CALLBACK OnFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  378. {
  379.     // Setup five rotation matrices (for rotating text strings)
  380.     D3DXVECTOR3 vAxis1(1.0f,2.0f,0.0f);
  381.     D3DXVECTOR3 vAxis2(1.0f,0.0f,0.0f);
  382.     D3DXMatrixRotationAxis( &g_matObj1, &vAxis1, (float)fTime/2.0f  );
  383.     D3DXMatrixRotationAxis( &g_matObj2, &vAxis2, (float)fTime );
  384.  
  385.     D3DXMATRIX mScale;
  386.     D3DXMatrixScaling( &mScale, 0.5f, 0.5f, 0.5f );
  387.     g_matObj2 *= mScale;
  388.  
  389.     // Add some translational values to the matrices
  390.     g_matObj1._41 = 1.0f;   g_matObj1._42 = 6.0f;   g_matObj1._43 = 20.0f; 
  391.     g_matObj2._41 = -4.0f;  g_matObj2._42 = -1.0f;  g_matObj2._43 = 0.0f; 
  392. }
  393.  
  394.  
  395. //--------------------------------------------------------------------------------------
  396. // This callback function will be called at the end of every frame to perform all the 
  397. // rendering calls for the scene, and it will also be called if the window needs to be 
  398. // repainted. After this function has returned, the sample framework will call 
  399. // IDirect3DDevice9::Present to display the contents of the next buffer in the swap chain
  400. //--------------------------------------------------------------------------------------
  401. void CALLBACK OnFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime )
  402. {
  403.     HRESULT hr;
  404.     RECT rc;
  405.     D3DMATERIAL9 mtrl;
  406.     D3DXMATRIXA16 matWorld;
  407.  
  408.     // Get the view & projection matrix from camera.
  409.     // User can't control camera for this simple sample
  410.     D3DXMATRIXA16 matView = *g_Camera.GetViewMatrix();
  411.     D3DXMATRIXA16 matProj = *g_Camera.GetProjMatrix();
  412.     D3DXMATRIXA16 matViewProj = matView * matProj;
  413.  
  414.     pd3dDevice->SetTransform( D3DTS_VIEW,       &matView );
  415.     pd3dDevice->SetTransform( D3DTS_PROJECTION, &matProj );
  416.  
  417.     // Clear the viewport
  418.     pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L );
  419.  
  420.     // Begin the scene 
  421.     if( SUCCEEDED( pd3dDevice->BeginScene() ) )
  422.     {
  423.         UINT nHeight = DXUTGetPresentParameters().BackBufferHeight;
  424.  
  425.         DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"Demonstration Code" );
  426.  
  427.         // Demonstration 1:
  428.         // Draw a simple line using ID3DXFont::DrawText
  429.         {
  430.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Demonstration Part 1" );
  431. #if 1 
  432.             // Pass in DT_NOCLIP so we don't have to calc the bottom/right of the rect
  433.             SetRect( &rc, 150, 200, 0, 0 );        
  434.             g_pFont->DrawText( NULL, L"This is a trivial call to ID3DXFont::DrawText", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));
  435. #else
  436.             // If you wanted to calc the bottom/rect of the rect make these 2 calls
  437.             SetRect( &rc, 150, 200, 0, 0 );        
  438.             g_pFont->DrawText( NULL, L"This is a trivial call to ID3DXFont::DrawText", -1, &rc, DT_CALCRECT, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));
  439.             g_pFont->DrawText( NULL, L"This is a trivial call to ID3DXFont::DrawText", -1, &rc, 0, D3DXCOLOR( 1.0f, 0.0f, 0.0f, 1.0f ));
  440. #endif
  441.         }
  442.  
  443.         // Demonstration 2:
  444.         // Allow multiple draw calls to sort by texture changes by ID3DXSprite
  445.         // When drawing 2D text use flags: D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE
  446.         // When drawing 3D text use flags: D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_BACKTOFRONT
  447.         {
  448.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Demonstration Part 2" );
  449.             g_pTextSprite->Begin( D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE );
  450.             SetRect( &rc, 10, nHeight - 15*6, 0, 0 );        
  451.             g_pFont2->DrawText( g_pTextSprite, L"These multiple calls to ID3DXFont::DrawText() using the same ID3DXSprite.", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ));
  452.             SetRect( &rc, 10, nHeight - 15*5, 0, 0 );        
  453.             g_pFont2->DrawText( g_pTextSprite, L"ID3DXFont now caches letters on one or more textures.", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ));
  454.             SetRect( &rc, 10, nHeight - 15*4, 0, 0 );        
  455.             g_pFont2->DrawText( g_pTextSprite, L"In order to sort by texture state changes on multiple", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ));
  456.             SetRect( &rc, 10, nHeight - 15*3, 0, 0 );        
  457.             g_pFont2->DrawText( g_pTextSprite, L"draw calls to DrawText() pass a ID3DXSprite and use", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ));
  458.             SetRect( &rc, 10, nHeight - 15*2, 0, 0 );        
  459.             g_pFont2->DrawText( g_pTextSprite, L"flags D3DXSPRITE_ALPHABLEND | D3DXSPRITE_SORT_TEXTURE", -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ));
  460.             g_pTextSprite->End();
  461.         }
  462.  
  463.         // Demonstration 3:
  464.         // Word wrapping and unicode text.  
  465.         // Note that not all fonts support dynamic font linking. 
  466.         {
  467.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Demonstration Part 3" );
  468.             rc.left = 10;
  469.             rc.top = 60;
  470.             rc.right = DXUTGetPresentParameters().BackBufferWidth - 150;
  471.             rc.bottom = DXUTGetPresentParameters().BackBufferHeight - 10;
  472.             g_pFont2->DrawTextW( NULL, g_strTextBuffer, -1, &rc, DT_LEFT | DT_WORDBREAK | DT_EXPANDTABS, D3DXCOLOR( 1.0f, 0.0f, 1.0f, 1.0f ));
  473.         }
  474.  
  475.         // Demonstration 4:
  476.         // Draw 3D extruded text using a mesh created with D3DXFont
  477.         if( g_pMesh3DText != NULL )
  478.         {
  479.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"Demonstration Part 4" );
  480.             ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
  481.             mtrl.Diffuse.r = mtrl.Ambient.r = 0.0f;
  482.             mtrl.Diffuse.g = mtrl.Ambient.g = 0.0f;
  483.             mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;
  484.             mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
  485.             pd3dDevice->SetMaterial( &mtrl );
  486.             pd3dDevice->SetTransform( D3DTS_WORLD, &g_matObj2 );
  487.             g_pMesh3DText->DrawSubset(0);
  488.         }
  489.  
  490.         DXUT_EndPerfEvent(); // end of demonstration code
  491.  
  492.         {
  493.             CDXUTPerfEventGenerator g( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
  494.             V( g_HUD.OnRender( fElapsedTime ) ); 
  495.             V( g_SampleUI.OnRender( fElapsedTime ) );
  496.  
  497.             // Show frame rate
  498.             SetRect( &rc, 2, 0, 0, 0 );
  499.             g_pStatsFont->DrawText( NULL, DXUTGetFrameStats(), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ));
  500.             SetRect( &rc, 2, 15, 0, 0 );
  501.             g_pStatsFont->DrawText( NULL, DXUTGetDeviceStats(), -1, &rc, DT_NOCLIP, D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  502.         }
  503.         
  504.         // End the scene
  505.         pd3dDevice->EndScene();
  506.     }
  507. }
  508.  
  509.  
  510. //--------------------------------------------------------------------------------------
  511. // Before handling window messages, the sample framework passes incoming windows 
  512. // messages to the application through this callback function. If the application sets 
  513. // *pbNoFurtherProcessing to TRUE, then the sample framework will not process this message.
  514. //--------------------------------------------------------------------------------------
  515. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing )
  516. {
  517.     // Give the dialogs a chance to handle the message first
  518.     *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  519.     if( *pbNoFurtherProcessing )
  520.         return 0;
  521.     *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  522.     if( *pbNoFurtherProcessing )
  523.         return 0;
  524.  
  525.     // Pass all remaining windows messages to camera so it can respond to user input
  526.     g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  527.  
  528.     switch( uMsg )
  529.     {
  530.         case WM_SIZE:
  531.         {
  532.             if( SIZE_RESTORED == wParam )
  533.             {
  534.             //    if( !g_bMaximized && !g_bMinimized )
  535.                 {
  536.                     // This sample demonstrates word wrapping, so if the 
  537.                     // window size is changing because the user dragging the window 
  538.                     // edges we'll recalc the size, re-init, and repaint
  539.                     // the scene as the window resizes.  This would be very
  540.                     // slow for complex scene but works here since this sample 
  541.                     // is trivial.
  542.               /*      HandlePossibleSizeChange();
  543.  
  544.                     // Repaint the window
  545.                     if( g_pd3dDevice && !g_bActive && g_bWindowed &&
  546.                         g_bDeviceObjectsInited && g_bDeviceObjectsRestored )
  547.                     {
  548.                         HRESULT hr;
  549.                         Render();
  550.                         hr = g_pd3dDevice->Present( NULL, NULL, NULL, NULL );
  551.                         if( D3DERR_DEVICELOST == hr )
  552.                             g_bDeviceLost = true;
  553.                     }*/
  554.                 }
  555.             }
  556.             break;
  557.         }
  558.     }
  559.  
  560.     return 0;
  561. }
  562.  
  563.  
  564. //--------------------------------------------------------------------------------------
  565. // As a convenience, the sample framework inspects the incoming windows messages for
  566. // keystroke messages and decodes the message parameters to pass relevant keyboard
  567. // messages to the application.  The framework does not remove the underlying keystroke 
  568. // messages, which are still passed to the application's MsgProc callback.
  569. //--------------------------------------------------------------------------------------
  570. void CALLBACK KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown )
  571. {
  572.     if( bKeyDown )
  573.     {
  574.         switch( nChar )
  575.         {
  576.             case VK_F1: g_bShowHelp = !g_bShowHelp; break;
  577.         }
  578.     }
  579. }
  580.  
  581.  
  582. //--------------------------------------------------------------------------------------
  583. // Handles the GUI events
  584. //--------------------------------------------------------------------------------------
  585. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl )
  586. {
  587.     switch( nControlID )
  588.     {
  589.         case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break;
  590.         case IDC_TOGGLEREF:        DXUTToggleREF(); break;
  591.         case IDC_CHANGEDEVICE:     DXUTSetShowSettingsDialog( !DXUTGetShowSettingsDialog() ); break;
  592.         case IDC_CHANGEFONT:    
  593.         {
  594.             bool bWindowed = DXUTIsWindowed();
  595.             if( !bWindowed )
  596.                 DXUTToggleFullScreen();
  597.  
  598.             HDC hdc;
  599.             LONG lHeight;
  600.             hdc = GetDC( DXUTGetHWND() );
  601.             lHeight = -MulDiv( g_nFontSize, GetDeviceCaps(hdc, LOGPIXELSY), 72 );
  602.             ReleaseDC( DXUTGetHWND(), hdc );
  603.             hdc = NULL;
  604.  
  605.             LOGFONT lf;
  606.             lstrcpy( lf.lfFaceName, g_strFont );
  607.             lf.lfHeight = lHeight;
  608.  
  609.             CHOOSEFONT cf;
  610.             ZeroMemory( &cf, sizeof(cf) );
  611.             cf.lStructSize = sizeof(cf);
  612.             cf.hwndOwner   = DXUTGetHWND();
  613.             cf.lpLogFont   = &lf;
  614.             cf.Flags       = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_TTONLY;
  615.             
  616.             if( ChooseFont( &cf ) )
  617.             {
  618.                 LPD3DXFONT pFontNew = NULL;
  619.                 LPD3DXMESH pMesh3DTextNew = NULL;
  620.                 TCHAR* pstrFontNameNew = lf.lfFaceName;
  621.                 int dwFontSizeNew = cf.iPointSize / 10;
  622.                 bool bSuccess = false;
  623.                 bool bBold   = ((cf.nFontType & BOLD_FONTTYPE) == BOLD_FONTTYPE);
  624.                 bool bItalic = ((cf.nFontType & ITALIC_FONTTYPE) == ITALIC_FONTTYPE);
  625.  
  626.                 HDC hDC = GetDC( NULL );
  627.                 int nLogPixelsY = GetDeviceCaps(hDC, LOGPIXELSY);
  628.                 ReleaseDC( NULL, hDC );
  629.  
  630.                 int nHeight = -MulDiv(dwFontSizeNew, nLogPixelsY, 72);
  631.                 if( SUCCEEDED( D3DXCreateFont( DXUTGetD3DDevice(), nHeight, 0, bBold ? FW_BOLD : FW_NORMAL, 1, bItalic, DEFAULT_CHARSET, 
  632.                                                OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_DONTCARE, 
  633.                                                pstrFontNameNew, &pFontNew ) ) )
  634.                 {
  635.                     if( SUCCEEDED( CreateD3DXTextMesh( DXUTGetD3DDevice(), &pMesh3DTextNew, pstrFontNameNew, dwFontSizeNew, bBold, bItalic ) ) )
  636.                     {
  637.                         bSuccess = true;
  638.                         SAFE_RELEASE( g_pFont );
  639.                         g_pFont = pFontNew;
  640.                         pFontNew = NULL;
  641.  
  642.                         SAFE_RELEASE( g_pMesh3DText );
  643.                         g_pMesh3DText = pMesh3DTextNew;
  644.                         pMesh3DTextNew = NULL;
  645.  
  646.                         lstrcpy( g_strFont, pstrFontNameNew );
  647.                         g_nFontSize = dwFontSizeNew;
  648.                     }
  649.                 }
  650.                 
  651.                 SAFE_RELEASE( pMesh3DTextNew );
  652.                 SAFE_RELEASE( pFontNew );
  653.  
  654.                 if( !bSuccess )
  655.                 {
  656.                     MessageBox( DXUTGetHWND(), TEXT("Could not create that font."), 
  657.                                 L"Text3D", MB_OK );
  658.                 }
  659.             }
  660.  
  661.             if( !bWindowed )
  662.                 DXUTToggleFullScreen();
  663.  
  664.             break;
  665.         }
  666.     }
  667. }
  668.  
  669.  
  670. //--------------------------------------------------------------------------------------
  671. // This callback function will be called immediately after the Direct3D device has 
  672. // entered a lost state and before IDirect3DDevice9::Reset is called. Resources created
  673. // in the OnResetDevice callback should be released here, which generally includes all 
  674. // D3DPOOL_DEFAULT resources. See the "Lost Devices" section of the documentation for 
  675. // information about lost devices.
  676. //--------------------------------------------------------------------------------------
  677. void CALLBACK OnLostDevice()
  678. {
  679.     if( g_pStatsFont )
  680.         g_pStatsFont->OnLostDevice();
  681.     if( g_pFont )
  682.         g_pFont->OnLostDevice();
  683.     if( g_pFont2 )
  684.         g_pFont2->OnLostDevice();
  685.     if( g_pTextSprite )
  686.         g_pTextSprite->OnLostDevice();
  687.     SAFE_RELEASE( g_pMesh3DText );
  688. }
  689.  
  690.  
  691. //--------------------------------------------------------------------------------------
  692. // This callback function will be called immediately after the Direct3D device has 
  693. // been destroyed, which generally happens as a result of application termination or 
  694. // windowed/full screen toggles. Resources created in the OnCreateDevice callback 
  695. // should be released here, which generally includes all D3DPOOL_MANAGED resources. 
  696. //--------------------------------------------------------------------------------------
  697. void CALLBACK OnDestroyDevice()
  698. {
  699.     SAFE_RELEASE( g_pFont );
  700.     SAFE_RELEASE( g_pFont2 );
  701.     SAFE_RELEASE( g_pStatsFont );
  702.     SAFE_RELEASE( g_pTextSprite );
  703. }
  704.  
  705.  
  706.  
  707.